//==============================================================================

#ifndef ALIST_H
  #define ALIST_H

//==============================================================================

template <class TypeItem> class aItem
{
  public:
    aItem<TypeItem>()
    {
      next = 0;
      prev = 0;
    };
    ~aItem<TypeItem>()
    {
    };
    
    aItem* next;
    aItem* prev;
    TypeItem data;
};

//==============================================================================

template <class Type> class aList
{
  public:
    inline aItem<Type>* alGetLastItem() const     {return last;}
    inline aItem<Type>* alGetFirstItem() const    {return items;}
    inline int alGetCount() const                 {return count;}

    aList()
    {
      items = 0;
      last = 0;
      count = 0;
    }
    ~aList()
    {
      alRemoveItems();
    }

    aItem<Type>* alAddItem()
    {
      if (!items)
      {
        items = new aItem<Type>;
        last = items;
        ++count;
    
        return items;
      }
  
      aItem<Type>* tmpItem = this->alGetLastItem();

      tmpItem->next = new aItem<Type>;
      tmpItem->next->prev = tmpItem;

      last = tmpItem->next;
      ++count;
  
      return last;
    }
    void alRemoveItems()
    {
      if (!items)
        return;

      aItem<Type>* tmpItem = alGetLastItem();
      aItem<Type>* tmpItem2 = 0;
  
      while(1)
      {
        tmpItem2 = tmpItem->prev;
    
        delete tmpItem;
    
        if (tmpItem2)
          tmpItem = tmpItem2;
        else
          break;
      }
      items = 0;
      last = 0;
      count = 0;
    }
    void alRemoveLastItem()
    {
      if (items)
      {
        if (last->prev)
        {
          last->prev = 0;

          delete last;
        }
        else
        {
          delete items;
          
          items = 0;
        }
        last = 0;
        --count;
      }
    }
    void alCopyItems(aList<Type>& to)const
    {
      to.alRemoveItems();

      aItem<Type>* tmpItem = items;

      while(tmpItem)
      {
        to.alAddItem()->data = tmpItem->data;

        tmpItem = tmpItem->next;
      }
    }
    void alRemoveItem(aItem<Type>* it)
    {
      if (!it || !alFoundItem(it))
        return;

      if (it == items)
        if (items->next)
        {
          aItem<Type>* it2 = items->next;
          
          it2->prev = 0;

          delete items;

          items = it2;
        }
        else
        {
          delete items;

          items = 0;
          last = 0;
        }
      else
      {
        if (it->next)
          it->next->prev = it->prev;
        if (it->prev)
          it->prev->next = it->next;

        if (it == last)
          last = it->prev;
        
        delete it;
      }
      --count;
    }
    
  private:
    bool alFoundItem(aItem<Type>* it)
    {
      aItem<Type>* tmpItem = last;

      while(tmpItem)
      {
        if (tmpItem == it)
          return 1;

        tmpItem = tmpItem->prev;
      }

      return 0;
    }

  private:
    aItem<Type>* items;
    aItem<Type>* last;
    int count;
};

//==============================================================================

#endif

//==============================================================================
